.TH LIBPFM 3  "November, 2002" "" "Linux Programmer's Manual"
.SH NAME
pfm_dispatch_events \- setup PMC arguments
.SH SYNOPSIS
.nf
.B #include <perfmon/pfmlib.h>
.sp
.BI "int pfm_dispatch_events(pfmlib_param_t *"param ");"
.sp
.SH DESCRIPTION
This function is the central piece of the library. It is important to understand
that the library does not effectively program the PMU, i.e., it does not make
any kernel \fBperfmonctl()\fR call. The PMU is never actually accessed by the 
library. Instead, the library helps applications prepare the arguments to pass to
the kernel, in particular it can setup the values to write into the PMC registers.
The application describes what it wants to measure in the \fBparam\fR argument
of type \fBpfmlib_param_t\fR and the resulting values for the PMC will be stored 
in a table in that structure.
.sp
The typical sequence of calls first starts by initializing the library, then
each event to be monitored is searched using variations of the \fBpfm_find_event\fR
function. The results are stored into the \fBpfmlib_param_t\fR structure. Other
adjustments are made in this structure. Then \fBpfm_dispatch_events\fR is called.
Upon successful return from this function, the PMC registers can be programmed using 
the \fBPFM_WRITE_PMCS\fB command using the values returned by \fBpfm_dispatch_events\fR.
.sp
The \fBpfmlib_param_t\fR structure is defined as follows:
.sp
.nf
typedef struct 
	int          event;
	unsigned int plm;
} pfmlib_event_t;

typedef struct {
	unsigned int   pfp_event_count;
	unsigned int   pfp_pc_count;
	unsigned int   pfp_flags;
	unsigned int   pfp_dfl_plm;
	pfmlib_event_t pfp_events[PMU_MAX_PMCS];
	pfarg_reg_t    pfp_pc[PMU_MAX_PMCS];

	void           *pfp_model;
} pfmlib_param_t;
.fi
.sp
The structure mostly contains two tables. The first one, called \fBpfp_events\fR describes
the events to be measured and is given as input. The second table, called \fBpfp_pc\fR
is used to stores the values for each of the PMC involved in the PMU configuration matching
the description in \fBparam\fR.  The number of submitted events is indicated by 
\fBpfp_event_count\fR, i.e., the number of valid entries in \fBpfp_events\fR. The
number of valid entries in \fBpfp_pc\fR is stored in \fBpfp_pc_count\fR and is only
valid upon successful return from the call. Depending on the PMU implementation,
the number of PMC registers to program can be bigger than the number of submitted events.
The application must never use \fBpfp_event_count\fR to represent the number of PMCS.

Each event, in a \fBpfmlib_event_t\fR, is represented by its opaque descriptor, which must have been 
obtained with \fBpfm_find_event()\fR or derivatives, and a privilege level mask in \fBplm\fR. 
The \fBplm\fR field is a bitmask where each bit indicates a set of privilege levels at which to monitor. 
The IA-64 architecture support four different levels, 0 being the most privileged level used by the 
kernel and 3 being the least privileged level used by all applications. It is possible to monitor 
at more than one level at a time. The library defines a set of constant to designate privilege levels:
.TP
.B PFM_PLM0
monitor at the kernel privilege level
.TP 
.B PFM_PLM1
monitor at privilege level 1
.TP 
.B PFM_PLM2
monitor at privilege level 2
.TP 
.B PFM_PLM3
monitor at the user privilege level
.sp
.LP
To monitor at both level and kernel levels for the first event, the application
can simply use:
.sp
.nf
event[0].plm = PFM_PLM0|PFM_PLM3;
.fi
.sp
.sp
Events with a \fBplm\fR value of 0 will use the default privilege level mask
as indicated by \fBpfp_dfl_plm\fR which must be set to any combinations of
values described above. It is illegal to have a value of 0 for this field.
.sp
The IA-64 PMU supports two different types of performance monitors: user
and privileged monitors. They are not radically different in nature but
they are controlled using two distinct mechanisms allowing concurrent
use. The user monitors are designed to monitor per process execution.
The  privilege monitors are designed to monitor an entire system , i.e.,
for a system wide monitoring session. The kernel enforces this distinction
and the library needs to know about it because it affects the way the
PMC registers are programmed. For all system wide sessions, the
user must set the \fBPFMLIB_PFP_SYSTEMWIDE\fR in the \fBpfp_flags\fR
field to ensure proper programming of the PMC registers. When this 
flag is not set, the library will assume the application is using
user monitors for a per-process session.
.sp
The \fBpfp_model\fR field is pointing to an optional PMU model specific
extension to the \fBpfmlib_param_r\fR structure. Some models support
more advanced features than what is specified in the architecture. 
The model specific module of the library knows about those extensions 
and can program additional PMC registers when necessary. Even though 
existing PMU models do have extensions, applications are not required 
to use them to setup interesting monitoring sessions. This is typically
true when an application only does counting of events. If this field is NULL then 
the model specific features will not be accessible to the application. Information 
about model specific support for this library is provided in separate man pages.
.SH EXAMPLE
A typical sequence of operation to monitor \fBCPU_CYCLES\fR for
a per-process session is as follows:
.nf
	#include <perfmon/pfmlib.h>
	...
	pfmlib_param_t param;
	pfarg_context_t ctx[1];
	pfarg_reg_t pd[1];
	int ret;

	if (pfm_initialize() != PFMLIB_SUCCESS) {
		fprintf(stderr, "can't initialize library\\n");
		exit(1);
	}
	memset(&param,0, sizeof(param));
	memset(pd, 0, sizeof(pd));

	ret = pfm_find_event("cpu_cycles", &param.pfp_events[0].event);
	if (ret != PFMLIB_SUCCESS) {
		fprintf(stderr, "cannot find cpu_cycles event\\n");
		exit(1);
	}
	param.pfp_dfl_plm     = PFM_PLM3; 
	param.pfp_event_count = 1;

	ret = pfm_dispatch_events(&param);
	if (ret != PFMLIB_SUCCESS) {
		fprintf(stderr, "cannot dispatch: %s\\n", pfm_strerror(ret));
		exit(1);
	}
	/* match the PMD register with the PMC controlling it (for counters) */
	pd[0].reg_num = evt.pfp_pc[0].reg_num;
	...
	if (perfmonctl(getpid(), PFM_CREATE_CONTEXT, ctx, 1) == -1 ) {
		...
	}

	if (perfmonctl(getpid(), PFM_ENABLE, NULL, 0) == -1) {
		...	
	}
	if (perfmonctl(getpid(), PFM_WRITE_PMCS, evt.pfp_pc, evt.pfp_pc_count) == -1) {
		...
	}
	if (perfmonctl(getpid(), PFM_WRITE_PMDS, pd, evt.pfp_event_count) == -1) {
		...
	}
	pfm_start();
	/* code to monitor */
	pfm_stop();

	if (perfmonctl(getpid(), PFM_READ_PMDS, pd, evt.pfp_event_count) == -1) {
		...
	}
	printf("results: %lu\n", pd[0].reg_value);
	...
.fi

.SH RETURN
The function returns whether or not the call was successful.
A return value of \fBPFMLIB_SUCCESS\fR indicates sucess, 
otherwise the value is the error code.
.SH ERRORS
.B PFMLIB_ERR_NOINIT
The library has not been initialized properly.
.TP
.B PFMLIB_ERR_INVAL
Some arguments were invalid. For instance the value of *count is zero.
This can also be due to he content of the \fBpfmlib_param_t\fR structure.
.TP
.B PFMLIB_ERR_NOTFOUND
No matching event was found.
.TP
.B PFMLIB_ERR_TOOMANY
The number of events to monitor exceed the number of implemented counters.
.TP
.B PFMLIB_ERR_NOASSIGN
The events cannot be dispatched to the PMC because events have conflicting constraints.
.TP
.B PFMLIB_ERR_MAGIC
The model specific extension does not have the right magic number.
.TP
.B PFMLIB_ERR_FEATCOMB
The set of events and features cannot be combined.
.TP
.B PFMLIB_ERR_EVTMANY
An event has been supplied more than once and is causing resource (PMC) conflicts.
.TP
.B PFMLIB_ERR_IRRINVAL
Invalid code range restriction (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_IRRALIGN
Code range has invalid alignment (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_IRRTOOMANY
Cannot satisfy all the code ranges (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_DRRTOOMANY
Cannot satisfy all the data ranges (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_DRRINVAL
Invalid data range restriction (Itanium, Itanium 2).
.TP
.B PFMLIB_ERR_EVTSET
Some events belong to incompatible sets (Itanium 2).
.TP
.B PFMLIB_ERR_EVTINCOMP
Some events cannot be measured at the same time (Itanium 2).
.TP
.B PFMLIB_ERR_IRRTOOBIG
Code range is too big (Itanium 2).
.SH SEE ALSO
pfmlib_itanium(3), pfmlib_itanium2(3)
.SH AUTHOR
Stephane Eranian <eranian@hpl.hp.com>
.PP
